35C3-POST WriteUp


题目&wp链接:
https://github.com/eboda/35c3/tree/master/post

35C3-POST
hint: flag is in db
Hint2: the lovely XSS is part of the beautiful design and insignificant for the challenge
Hint3: You probably want to get the source code, luckily for you it’s rather hard to configure nginx correctly.

功能点很简单,注册,登录,上传文件,评论。

测试了< >被实体编码,上传php文件不解析。

提示xss无用,nginx配置有问题,在Vulhub中提到了常见的nginx配置问题。

结合提示中的源码泄露,这里尝试nginx的alias配置不当导致目录穿越漏洞。
整个过程就一个uploads目录,构造payload:https://50.3.232.201:8000/uploads../

得到一个default.backup:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
server {
listen 80;
access_log /var/log/nginx/example.log;

server_name localhost;

root /var/www/html;

location /uploads {
autoindex on;
alias /var/www/uploads/;
}

location / {
alias /var/www/html/;
index index.php;

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
}

location /inc/ {
deny all; # 禁止直接访问
}
}

server {
listen 127.0.0.1:8080;
access_log /var/log/nginx/proxy.log;

if ( $request_method !~ ^(GET)$ ) {
return 405;
}
root /var/www/miniProxy;
location / {
index index.php;

location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
}
}

说明8080端口还有另一个服务,即在/var/www/miniProxy目录下,直接访问https://50.3.232.201:8000/uploads../miniProxy/可以直接下载php源码,不会解析,这个页面的功能大概就是web的proxy。

此外,通过目录穿越可以下载到全部php源码。

源码基本浏览了一遍,加上提示,我们要拿到数据库里面的flag,在db.php的38行出中有一处反序列化操作unserialize()
image_1d3t44d2d1e1j421ciln9ni5i9.png-69.1kB
而该函数的功能是将从数据库取出的数据进行反序列化操作,db.php的52行:
image_1d3t460c91rgpvdv10sj1ne1ucem.png-69.8kB

所以我们要想控制这个unserialize()函数,就得先往数据库里面插入我们的数据,55行:
image_1d3t487qa1d4ci1ks04jclcmn13.png-65.8kB

全局搜索insert操作,共两处,一处注册,一处提交post数据。
image_1d3t49dromul7auqt8ei41fml1g.png-160.2kB

post.php的41行:
image_1d3tov9ne1fug19ol11p153l3ut3d.png-104.1kB

全局搜索save()函数,在default.php的19行:
image_1d3tp1kep10hurlojai2h0bo647.png-173.7kB

save()函数中insert(),在db.php中的55行
image_1d3tv92gb1irns0iitmqo8125i9.png-84.6kB

再跟进DB::prepare_params(),db.php的18行:
image_1d3tvh90e6peueunqc1n1e1438m.png-80.5kB

这里中途对array_map()没理解好,卡了很久:https://php.net/manual/en/function.array-map.php

到这里,我们要传入一个$serializedobject$开头的字符串,才能使得查库操作时触发我们的unserialize(),但insert的时候过滤了这个字符串前缀,在官方的wp中提到,我们可以使用全角符号的unicode字符,mssql会自动转换,以$符号存入数据库中。
image_1d3u04oab2oc5ol1b0fl9pouk13.png-80.9kB

这里0xEF 0xBC 0x84会被mssql存储为$

下面构造反序列化的攻击链:
首先default.php 73行
image_1d3u3btl0os41sob1kk71qac11o0p.png-72.7kB
调用了post.php的63行,使用了query函数查询
image_1d3u3dhltqr01jm413e2bht1ud416.png-118kB

同时在post.php中的Attachment类
image_1d3u3fjs09i1ri1c3j1a1d17la1j.png-149.5kB

控制$za属性传入soapClient类,使之在上图19行调用了open()方法,因为不存在,所以触发soapClient的__call方法(这里猜想有soap服务,另一个8080端口的服务暗示我们了ssrf,加上这里unserialize的利用功能点少)

payload:
image_1d3v4ki6415jrro18ek17t11r799.png-44.6kB

$用brup的hex修改
image_1d3v4l7rnb98n38c8s1mrj4aqm.png-60.4kB

8080端口服务只允许get型数据,但是从其服务中来看我们要用post型去打内网数据库,所以这里就利用soapclient的clrf发起get请求,gopher模拟post
image_1d3v5h7ca5q11lktsi8j391akf1g.png-155.2kB